#include "../Include/TimeManager.h"
#include "../Include/Assert.h"
#include "../Include/Timer.h"
#include "../Include/OS.h"
#include "../Include/Macro.h"
#include <iostream>
#include <vector>
using namespace std;

#ifndef  LINUX_HAVE_TIMERFD

CTimeManager::CTimeManager()
{
	AtomicInit(&m_nAtomicInit);
}

CTimeManager::~CTimeManager()
{
	if (m_timeheap.p != nullptr)
	{
		free(m_timeheap.p);
		m_timeheap.p = nullptr;
	}
}

Bool CTimeManager::Initialize()
{
	TimerEventStruct** p;
	if (!(p = (TimerEventStruct**)malloc(10000 * sizeof(TimerEventStruct *))))
	{
		return False;
	}
	
    m_timeheap.a = 10000;
    m_timeheap.p = p;
    m_timeheap.n = 0;
	
	return True;
}

Int64 CTimeManager::GetMinTime()
{
	Int64 nRealTimeout = 10000;
	AtomicLock(&m_nAtomicInit);

	do
	{
		if (min_heap_empty_(&m_timeheap))
		{
			break;
		}
		
		TimerEventStruct *pTimer = min_heap_top_(&m_timeheap);
		Assert(pTimer != NULL);
		
		nRealTimeout = pTimer->lTimeout - OS::Milliseconds();
		if (nRealTimeout < 0)
		{
			nRealTimeout = 0;
		}

	} while (False);
	
	AtomicUnlock(&m_nAtomicInit);
	return nRealTimeout;
}

Bool CTimeManager::AddTimer(CTimer* lpTimer)
{
	AtomicLock(&m_nAtomicInit);
    TimerEventStruct* pTimerItem = lpTimer->GetTimerEventStruct();

	if (min_heap_reserve_(&m_timeheap, 1 + min_heap_size_(&m_timeheap)) == -1)
	{
		AtomicUnlock(&m_nAtomicInit);
		return False;
	}
    pTimerItem->lTimeout = OS::Milliseconds() + pTimerItem->nInterval;
	min_heap_elem_init_(pTimerItem);
	Int32  nRet = min_heap_push_(&m_timeheap, pTimerItem);
    pTimerItem->bDelFlag = False;
	
	AtomicUnlock(&m_nAtomicInit);
	return (nRet == 0);
}

Bool CTimeManager::DelTimer(CTimer* lpTimer)
{
	Int32 nRet = 0;
	AtomicLock(&m_nAtomicInit);
	if (!lpTimer->GetTimerEventStruct()->bDelFlag)
	{
		nRet = min_heap_erase_(&m_timeheap, lpTimer->GetTimerEventStruct());
		lpTimer->GetTimerEventStruct()->bDelFlag = True;
	}
	AtomicUnlock(&m_nAtomicInit);
	return (nRet == 0);
}

Bool CTimeManager::IsTop(CTimer* lpTimer)
{
	AtomicLock(&m_nAtomicInit);
	Int32 nRet = min_heap_elt_is_top_(lpTimer->GetTimerEventStruct());
	AtomicUnlock(&m_nAtomicInit);
	
	return (nRet == 1);
}

Bool CTimeManager::DealTimer()
{
	TimerEventStruct *pTimerItem;
	Int64 now = OS::Milliseconds();
	
	AtomicLock(&m_nAtomicInit);
	if (min_heap_empty_(&m_timeheap))
	{
		AtomicUnlock(&m_nAtomicInit);
		return True;
	}
	
	std::vector<TimerEventStruct*> vecDealEvent;
	while ((pTimerItem = min_heap_top_(&m_timeheap)))
	{
		if (now < pTimerItem->lTimeout)
		{
			break;
		}
		
		if (!pTimerItem->bDelFlag)
		{
			min_heap_pop_(&m_timeheap);
			pTimerItem->bDelFlag = True;
			vecDealEvent.push_back(pTimerItem);
		}
	}
	AtomicUnlock(&m_nAtomicInit);
	
	for (std::vector<TimerEventStruct*>::iterator it = vecDealEvent.begin(); it != vecDealEvent.end(); ++it)
	{
        AddTimer((*it)->pTimer);
		(*it)->pTimer->GetTimerEvent()->OnTimer((*it)->pTimer);
       
	}
	
	return True;
}

void CTimeManager::OnMessageEvent(Int32 nMessageID, void *wParam, void *lParam)
{
}
#endif // ! LINUX_HAVE_TIMERFD
